package com.cctc.juc.source.Bitc.Glock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * [ReentrantLock 可重入锁（常用）]
 * 简介：ReentrantLock 是 JUC 显式锁的一个基础实现类，实现了 Lock 接口，除了拥有与 Java 内置锁相同的并发性和内存语义之外，还具备一些高级锁特性，例如非阻塞抢占、限时阻塞抢占、可中断抢占，以及支持维护多个同步队列，以提高锁的使用效率等；此外，由于 ReentrantLock 内部依赖于一个基于 AQS 基类实现的 Sync 同步器实例实现独占锁的抢占与释放逻辑，同时支持公平和非公平两种抢锁模式，并在竞争激烈的情况下，可以表现出比 Java 内置（重量级）锁更佳的性能。
 * 要求：[（熟练）手撕] 核心逻辑代码。
 * - ReentrantLock 是 [独占锁] 的一个标准实现类，适用于 “写多读少，多读多写” 的场景。
 * - ReentrantLock 是 [可重入锁] 的一个标准实现类，所谓 [可重入锁]，又称为 [递归锁]，指的是一个线程在其函数调用链的不同方法内，可以多次抢占同一把锁。
 * - ReentrantLock 是 [非公平锁 & 公平锁] 的一个标准实现类。
 * 综上，ReentrantLock 拥有与 Java 内置锁相同的并发性和内存语义。
 * 除此之外，ReentrantLock 实现了 Lock 接口，还具备一些高级锁特性，例如非阻塞抢占、限时阻塞抢占、可中断抢占，以及支持维护多个同步队列，以提高锁的使用效率等；此外，由于 ReentrantLock 内部依赖于一个基于 AQS 基类实现的 Sync 同步器实例实现（独占）锁的抢占与释放逻辑，并在竞争激烈的情况下，可以表现出比 Java 内置锁更佳的性能。
 */
public class ReentrantLock_AAAAA implements Lock {
    /**
     * [同步（基）类]。
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        /**
         * 抢锁逻辑：
         * - 公平模式；
         * - 非公平模式；
         * 具体逻辑交由子类实现。
         */
        abstract void lock();

        @Override
        protected final boolean tryRelease(int releases) {
            /**
             * 尝试解锁逻辑：
             * 提示：只有持锁的线程才有权限解锁，否则将抛出非法监视器状态异常。
             * 解锁，然后计算锁状态，判断锁状态是否为 0？
             * - 如果为 0，说明为最后一次解锁，释放锁，返回 true；
             * - 如果不为 0，说明不是最后一次解锁，更新锁（重入）状态，继续持有锁，返回 false。
             */
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }
    }

    /**
     * [公平模式同步器]。
     */
    static final class FairSync extends Sync {

        @Override
        final void lock() {
            /**
             * 公平模式抢锁。
             */
            acquire(1);
        }

        @Override
        protected final boolean tryAcquire(int acquires) {
            /**
             * 公平模式（FIFO）尝试加锁逻辑：
             * 1. 当锁状态为 0 时（已释放），判断是否存在前驱节点？
             * 1）如果不存在，说明前面没有排队线程，轮到自己了，占有锁，返回 true；
             * 2）如果存在，说明还没轮到自己，直接返回 false；
             * 2. 当锁状态不为 0 时（未释放），判断当前线程是否为持锁线程？
             * - 如果是，更新锁（重入）状态，返回 true；
             * - 如果不是，直接返回 false。
             * 严格按照 FIFO 的顺序加锁，绝对地公平。
             */
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            } else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) throw new Error("超过最大锁计数。");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

    /**
     * [非公平模式同步器]。
     */
    static final class NofairSync extends Sync {

        @Override
        final void lock() {
            /**
             * 非公平模式抢锁。
             * - 允许当前线程与排队线程同时抢锁。
             */
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
            } else acquire(1);
        }

        @Override
        protected final boolean tryAcquire(int acquires) {
            /**
             * 非公平模式尝试加锁逻辑：
             * 1. 当锁状态为 0 时（已释放），允许当前线程与排队线程同时加锁。
             * 2. 当锁状态不为 0 时（未释放），判断当前线程是否为持锁线程？
             * - 如果是，更新锁（重入）状态，返回 true；
             * - 如果不是，直接返回 false。
             */
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            } else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) throw new Error("超过最大锁计数。");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

    // 核心属性：基于 AQS 的同步器实例
    private final Sync sync;

    /**
     * 构造器：默认为非公平模式。
     */
    public ReentrantLock_AAAAA() {
        sync = new NofairSync();
    }

    /**
     * 构造器：显式指定公平、非公平模式。
     *
     * @param fair true-公平模式，false-非公平模式。
     */
    public ReentrantLock_AAAAA(boolean fair) {
        sync = fair ? new FairSync() : new NofairSync();
    }

    @Override
    public void lock() {
        sync.lock();
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return ((NofairSync) sync).tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }
}
